#include "io.h"
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/fs.h>
#include <linux/file.h>
#include "my_poll.h"

int send(int fd, const void *buf, int len, int flags){

    struct msghdr msg;
    mm_segment_t oldfs; // mm_segment_t is just a long
    struct iovec iov; // structure containing a base addr. and length
    int len2;
    int err;

    struct socket *sock = sockfd_lookup(fd, &err);
    if(sock==NULL){
	printk("cannot find sock %d\n", fd);
	return -1;
    }
    msg.msg_name = 0;
    msg.msg_namelen = 0;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1; //point to be noted
    msg.msg_control = NULL;
    msg.msg_controllen = 0;

    msg.msg_flags = MSG_NOSIGNAL;//0/*MSG_DONTWAIT*/;

    iov.iov_base = (char*) buf; // as we know that iovec is
    iov.iov_len = (__kernel_size_t) len; // nothing but a base addr and length


    oldfs = get_fs(); set_fs(KERNEL_DS);

    len2 = sock_sendmsg(sock,&msg,(size_t)(len));

    set_fs(oldfs);


    return len2;
}

int recv(int fd, void *buf, int len, int flags){
    struct msghdr msg;
    struct iovec iov;

    int len2;
    mm_segment_t oldfs;
    int err;
    struct socket *sock = sockfd_lookup(fd, &err);
    if(sock==NULL){
        printk("cannot find sock %d\n", fd);
        return -1;
    }

    msg.msg_name = 0;
    msg.msg_namelen = 0;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;

    iov.iov_base = buf;
    iov.iov_len = (size_t)len;


    oldfs = get_fs(); set_fs(KERNEL_DS);
    len2 = sock_recvmsg(sock,&msg,len,0/*MSG_DONTWAIT*/); // let it wait if there is no message
    set_fs(oldfs);

    return len2;
}

int poll(struct pollfd *fds, int nfds, int timeout){
    return my_poll(fds, nfds, timeout);
}

int write(struct file* filp, const void *buf, int len){
    mm_segment_t oldfs;
    int ret;
    oldfs = get_fs(); set_fs(KERNEL_DS);
    ret = filp->f_op->write(filp, buf, len, &filp->f_pos);
    set_fs(oldfs);
    return ret;
}

int read(struct file* filp, void *buf, int len){
    mm_segment_t oldfs;
    int ret;
    oldfs = get_fs(); set_fs(KERNEL_DS);
    ret = filp->f_op->read(filp, buf, len, &filp->f_pos);
    set_fs(oldfs);
    return ret;
}


